package com.logger.query;

import java.util.Scanner;
import java.util.regex.Matcher;

import com.fmk.utils.RegExpUtils;
import com.fmk.utils.StringUtils;

/**
 * 
 * @author bbarhoumi
 * 
 */
public class QueryFormatter {
    private static final String REPLACEMENT_RIGHT_PARENTHESIS = ") ";
    private static final String REPLACEMENT_LEFT_PARENTHESIS  = " (";
    private static final String ONE_SPACE                     = " ";
    private static final String ECT                           = "...";
    private static final int    NBR_PREVIEW_CHARACTERS        = 100;
    /**
     * Original query
     */
    private final String        sqlQuery;
    /**
     * Transformed Query
     */
    private String              rawSqlQuery;

    /**
     * Constructor
     * 
     * @param sqlQuery
     */
    public QueryFormatter(final Object obj) {
        this.sqlQuery = obj == null ? null : obj.toString();
    }

    public String getRawQuery() {
        if (this.rawSqlQuery == null && this.sqlQuery != null) {
            this.rawSqlQuery = QueryFormatter.getRawQuery(this.sqlQuery);
        }
        return this.rawSqlQuery;
    }

    /**
	 *
	 */
    public String getPreview() {
        final String rawQuery = this.sqlQuery;
        return QueryFormatter.getPreview(rawQuery);
    }

    /**
     * 
     * @param obj
     * @return
     */
    public static String getPreview(final Object obj) {
        if (obj == null) {
            return null;
        }
        final String rawQuery = QueryFormatter.getRawQuery(obj);
        final String preview;
        if (rawQuery != null && rawQuery.length() > QueryFormatter.NBR_PREVIEW_CHARACTERS) {
            final int indexOfSpace = rawQuery.indexOf(QueryFormatter.ONE_SPACE, QueryFormatter.NBR_PREVIEW_CHARACTERS);
            preview = rawQuery.substring(0, indexOfSpace == -1 ? QueryFormatter.NBR_PREVIEW_CHARACTERS : indexOfSpace).concat(QueryFormatter.ECT);
        } else {
            preview = rawQuery;
        }
        return preview;
    }

    /**
     * Make query easy to read, just one line
     * 
     * @param obj Text to be transformed
     * @return simple query in one line
     */
    public static String getRawQuery(final Object obj) {
        if (obj == null) {
            return null;
        }
        final String _sqlQuery = obj.toString();
        final StringBuilder sbRawQuery = new StringBuilder();
        final Scanner scanner = new Scanner(_sqlQuery);
        while (scanner.hasNextLine()) {
            final String line = scanner.nextLine();
            final String withoutComments = QueryFormatter.removeComments(line);
            if (withoutComments != null) {
                final String indentParenthese = QueryFormatter.indentParenthese(withoutComments);
                sbRawQuery.append(QueryFormatter.ONE_SPACE);
                sbRawQuery.append(indentParenthese);
            }
        }
        final String replaceSpaces = QueryFormatter.replaceSpaces(sbRawQuery);
        return replaceSpaces;
    }

    /**
     * 
     * @param obj
     * @return
     */
    public static String replaceSpaces(final Object obj) {
        if (obj == null) {
            return null;
        }
        final String string = obj.toString();
        if (string == null) {
            return string;
        }
        return string.replaceAll(RegExpUtils.Constants.REGX_TWO_SPACES, QueryFormatter.ONE_SPACE);
    }

    /**
     * 
     * @param obj
     * @return
     */
    public static String indentParenthese(final Object obj) {
        if (obj == null) {
            return null;
        }
        final String string = obj.toString();
        String newString = string.replaceAll(RegExpUtils.Constants.REGX_LEFT_PARENTHESIS, QueryFormatter.REPLACEMENT_LEFT_PARENTHESIS);
        newString = newString.replaceAll(RegExpUtils.Constants.REGX_RIGHT_PARENTHESIS, QueryFormatter.REPLACEMENT_RIGHT_PARENTHESIS);
        return newString;
    }

    /**
     * 
     * @param obj
     * @return
     */
    public static String removeComments(final Object obj) {
        if (obj == null) {
            return null;
        }
        final String string = obj.toString();
        final Matcher matcher = RegExpUtils.createMatcher(string, RegExpUtils.Constants.REGX_QUERY_COMMENT);
        final String withoutComments = matcher.replaceAll(StringUtils.Constants.EMPTY);
        if (StringUtils.isEmpty(withoutComments)) {
            return null;
        }
        return withoutComments;
    }
}
